/*
 * =====================================================================================
 *
 *       Filename:  Iterator.cpp
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  2015年02月24日 19时13分27秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  LiuYi (), swliuyi@gmail.com
 *   Organization:  
 *
 * =====================================================================================
 */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <limits.h>
#include <iostream>
#include  <tr1/memory>

using namespace std;

template <typename T>
class Iterator
{
    public:
        virtual const T First() = 0;
        virtual const T Next() = 0;
        virtual bool IsDone() = 0;
        virtual const T CurrentItem() = 0;
};

template <typename T>
class Aggregate
{
    public:
        virtual Iterator<T> * CreateIterator() = 0;
};

template <typename T> class ConcreteIterator;

template <typename T>
class ConcreteAggreagte : public Aggregate<T>
{
    private:
        vector<T> m_items;
    public:
        Iterator<T> * CreateIterator()
        {
            return new ConcreteIterator<T>(*this);
        }
        int GetCount()
        {
            return m_items.size();
        }
        T operator [] (int index) const
        {
            return m_items[index];
        }
        void Add(const T & item)
        {
            m_items.push_back(item);
        }
};

template <typename T>
class ConcreteIterator : public Iterator<T>
{
    private:
        ConcreteAggreagte<T> m_aggregate;
        int m_current;
    public:
        ConcreteIterator(ConcreteAggreagte<T> aggregate):m_aggregate(aggregate), m_current(0){}
        const T First()
        {
            return m_aggregate[0];
        }
        const T Next()
        {
            T ret;
            m_current++;
            if( m_current < m_aggregate.GetCount() )
            {
                ret = m_aggregate[m_current];
            }
            return ret;
        }
        bool IsDone()
        {
            return m_current >= m_aggregate.GetCount() ? true : false;
        }
        const T CurrentItem()
        {
            return m_aggregate[m_current];
        }
};

int main(int argc, char *argv[])
{
    ConcreteAggreagte<string> a;
    a.Add("a");
    a.Add("b");
    a.Add("c");
    a.Add("d");
    a.Add("e");

    Iterator<string> * i = a.CreateIterator();

    string item = i->First();

    while( !i->IsDone() )
    {
        cout<<i->CurrentItem()<<endl;
        i->Next();
    }
}
